﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;

namespace ViSaw
{
    public partial class FormViewer : AbstractViewer
    {
        public const string NAME = "ViSaw";
        public const PictureBoxSizeMode DEFAULT_SIZE_MODE = PictureBoxSizeMode.CenterImage;
        
        private bool fullScreenFlag;
        private bool zoomFlag;

        private int offsetX;
        private int offsetY;

        private int layoutStartX;
        private int layoutStartY;
        private int layoutSizeDeltaX;
        private int layoutSizeDeltaY;

        [DllImport("user32.dll", EntryPoint = "ShowWindow")]
        public static extern int ShowWindow(int hwnd, int nCmdShow);
        public const int SW_SHOW = 5;
        public const int SW_HIDE = 0;

        [DllImport("user32.dll", EntryPoint = "SystemParametersInfo")]
        private static extern int SystemParametersInfo(int uAction, int uParam, ref Rectangle lpvParam, int fuWinIni);
        public const int SPIF_UPDATEINIFILE = 0x1;
        public const int SPI_SETWORKAREA = 47;
        public const int SPI_GETWORKAREA = 48;

        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);

        public FormViewer(string path)
            : base(path)
        {
            InitializeComponent();
            layoutStartX = flowLayoutPanel1.Location.X;
            layoutStartY = flowLayoutPanel1.Location.Y;
            layoutSizeDeltaX = this.Size.Width - flowLayoutPanel1.Width;
            layoutSizeDeltaY = this.Size.Height - flowLayoutPanel1.Height;
            string filter = getFilter();
            openFileDialog.Filter = "图像文件 (" + filter + ")|" + filter + "|所有文件 (*.*)|*.*";
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            reloadFileList(firstPicPath);
            loadPicture(firstPicPath);
        }

        private void loadPicture(string path) 
        {
            //TODO 检查文件是否为图像
            FileInfo imgFile = new FileInfo(path);
            if (File.Exists(path)==false)
            {
                MessageBox.Show("文件不存在！", "错误");
            }
            //TODO 捕获无法识别图像的异常
            reset();
            image = new Bitmap(path);
            pictureBox.SizeMode = DEFAULT_SIZE_MODE;
            pictureBox.Image = image;
            this.Text = imgFile.Name + " - " + NAME;
            //获取图像数据
            toolStripStatusFileName.Text = imgFile.Name;
            toolStripStatusFileSize.Text = getFileSize(imgFile.Length, true);
            toolStripStatusBitmapSize.Text = getImageSize();
            toolStripStatusLabelIndexOfAmount.Text = (indexInFileList+1) + "/" + fileList.Count;

            doResize();
        }

        private void reset() 
        {
            zoomFlag = false;
            pictureBox.Dock = DockStyle.None;
            pictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
            this.Controls.Remove(pictureBox);
            flowLayoutPanel1.Controls.Add(pictureBox);
            flowLayoutPanel1.Show();
        }

        private void zoomMode()
        {
            zoomFlag = true;
            pictureBox.Dock = DockStyle.None;
            pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
            flowLayoutPanel1.Controls.Remove(pictureBox);
            this.Controls.Add(pictureBox);
            flowLayoutPanel1.Hide();
        }

        /**
         * 全屏
         */
        private void doFullScreen() 
        {
            //return;
            Log.Debug("触发全屏");
            fullScreenFlag = !fullScreenFlag;
            this.SuspendLayout();
            if (fullScreenFlag)
            {
                SetFormFullScreen(fullScreenFlag);
                this.FormBorderStyle = FormBorderStyle.None;
                this.WindowState = FormWindowState.Maximized;
                this.Activate();
            }
            else
            {
                this.WindowState = FormWindowState.Normal;
                this.FormBorderStyle = FormBorderStyle.Sizable;
                SetFormFullScreen(fullScreenFlag);
                this.Activate();
            }
            this.ResumeLayout(false);
        }

        /**
         * 上一页
         */
        private void doPrevPage()
        {
            if (indexInFileList <= 0) return;
            gotoPage(indexInFileList - 1);
        }

        /**
         * 下一页
         */
        private void doNextPage()
        {
            if (indexInFileList+1 >= fileList.Count) return;
            gotoPage(indexInFileList + 1);
        }

        /**
         * 翻页
         */
        private void gotoPage(int index)
        {
            if (index<0 || index >= fileList.Count) return;
            Log.Debug("翻到图片"+index);
            indexInFileList = index;
            string path = fileList[indexInFileList].FullName;
            loadPicture(path);
        }

        /**
         * 放大
         */
        private void doZoomIn()
        {
            Log.Debug("放大");
            zoomMode();
            int width = (int)(pictureBox.Width * 1.1);
            int height = (int)(pictureBox.Height * 1.1);
            int x = flowLayoutPanel1.Location.X + flowLayoutPanel1.Width / 2 - width / 2;
            int y = flowLayoutPanel1.Location.Y + flowLayoutPanel1.Height / 2 - height / 2;
            pictureBox.SetBounds(x, y, width, height);
            this.toolStripStatusZoom.Text = getZoomRate();
        }

        /**
         * 缩小
         */
        private void doZoomOut()
        {
            Log.Debug("缩小");
            zoomMode();
            int width = (int)(pictureBox.Width * 0.9);
            int height = (int)(pictureBox.Height * 0.9);
            int x = flowLayoutPanel1.Location.X + flowLayoutPanel1.Width / 2 - width / 2;
            int y = flowLayoutPanel1.Location.Y + flowLayoutPanel1.Height / 2 - height / 2;
            pictureBox.SetBounds(x, y, width, height);
            this.toolStripStatusZoom.Text = getZoomRate();
        }

        private void doResize()
        {
            if (image == null) return;
            Log.Debug("调整窗体大小：" + this.Width + "x" + this.Height);
            //Log.Debug("同时改动layout大小：" + (this.Width - layoutSizeDeltaX) + "x" + (this.Height - layoutSizeDeltaY));
            string zoom = getZoomRate();
            //int layoutWidth = flowLayoutPanel1.Size.Width;
            //int layoutHeight = flowLayoutPanel1.Size.Height;
            //int toolStripHeight = this.statusStrip.Height;
            //int menuHeight = this.menuStrip.Height;
            //if ((layoutWidth >= image.Width) && (layoutHeight >= image.Height))
            //{
            //    this.pictureBox.SizeMode = DEFAULT_SIZE_MODE;
            //}
            //else
            //{
            //    this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
            //    int widthZoom = 100 * layoutWidth / image.Width;
            //    int heightZoom = 100 * layoutHeight / image.Height;
            //    int minZoom = (widthZoom < heightZoom) ? widthZoom : heightZoom;
            //    zoom = minZoom + "%";
            //}
            //zoom = getZoomRate();
            this.toolStripStatusZoom.Text = zoom;
        }

        protected string getZoomRate()
        {
            int menuHeight = this.menuStrip.Height;
            int layoutWidth = this.Width - layoutSizeDeltaX;
            int layoutHeight = this.Height - layoutSizeDeltaY;
            string zoom = "100%";
            if (zoomFlag)
            {
                //TODO 缩放模式，缩放率与原图大小以及pictureBox大小有关
                int widthZoom = 100 * pictureBox.Width / image.Width;
                int heightZoom = 100 * pictureBox.Height / image.Height;
                int minZoom = (widthZoom < heightZoom) ? widthZoom : heightZoom;
                zoom = minZoom + "%";
                //保持居中
                int x = layoutStartX + layoutWidth / 2 - pictureBox.Width / 2;
                int y = layoutStartY + layoutHeight / 2 - pictureBox.Height / 2;
                pictureBox.Location = new Point(x, y);
            }
            else
            {
                //TODO 正常模式，缩放率与原图大小以及layout大小有关
                if ((layoutWidth >= image.Width) && (layoutHeight >= image.Height))
                {
                    this.pictureBox.SizeMode = DEFAULT_SIZE_MODE;
                    zoom = "100%";
                }
                else
                {
                    this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                    int widthZoom = 100 * layoutWidth / image.Width;
                    int heightZoom = 100 * layoutHeight / image.Height;
                    int minZoom = (widthZoom < heightZoom) ? widthZoom : heightZoom;
                    zoom = minZoom + "%";
                }
                this.pictureBox.SetBounds(0, menuHeight, layoutWidth, layoutHeight);
            }
            return zoom;
        }

        private bool SetFormFullScreen(bool fullscreen)
        {
            Rectangle rectOld = Rectangle.Empty;
            Int32 hwnd = 0;
            hwnd = FindWindow("Shell_TrayWnd", null);//获取任务栏的句柄
            if (hwnd == 0)
            {
                //TODO 错误提示
                return false;
            }
            if (fullscreen)//全屏
            {
                ShowWindow(hwnd, SW_HIDE);//隐藏任务栏
                SystemParametersInfo(SPI_GETWORKAREA, 0, ref rectOld, SPIF_UPDATEINIFILE);//get  屏幕范围
                Rectangle rectFull = Screen.PrimaryScreen.Bounds;//全屏范围
                SystemParametersInfo(SPI_SETWORKAREA, 0, ref rectFull, SPIF_UPDATEINIFILE);//窗体全屏幕显示
            }
            else//还原 
            {
                ShowWindow(hwnd, SW_SHOW);//显示任务栏
                SystemParametersInfo(SPI_SETWORKAREA, 0, ref rectOld, SPIF_UPDATEINIFILE);//窗体还原
            }
            return true;
        }

        private void FullScreenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            doFullScreen();
        }

        private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void FormViewer_SizeChanged(object sender, EventArgs e)
        {
            doResize();
        }

        private void FormViewer_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.H || 
                e.KeyCode == Keys.K ||
                e.KeyCode == Keys.PageUp)
            {
                doPrevPage();
            }
            else if (e.KeyCode == Keys.J || 
                e.KeyCode == Keys.L ||
                e.KeyCode == Keys.PageDown)
            {
                doNextPage();
            }
            else if (e.KeyCode == Keys.F)
            {
                doFullScreen();
            }
            else if (e.KeyCode == Keys.I || e.KeyCode == Keys.Z) 
            {
                doZoomIn();
            }
            else if (e.KeyCode == Keys.O)
            {
                doZoomOut();
            }
            else if (e.KeyCode == Keys.Escape)
            {
                //暂时处理为退出，以后有其他作用
                this.Close();
            }
            else if (e.KeyCode == Keys.Q)
            {
                this.Close();
            }
        }

        private void OpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult dr = openFileDialog.ShowDialog();
            if (dr==DialogResult.OK)
            {
                string filePath = openFileDialog.FileName;
                reloadFileList(filePath);
                loadPicture(filePath);
            }
        }
    }
}
